/*
 * FirstDivide.cpp
 *
 *  Created on: 13/02/2014
 *      Author: root
 */

#include "FirstBranch.h"
#include "DppmParams.h"
#include "Tuple.h"
#include <iostream>
#include <stdlib.h>

using namespace std;

extern Tuple * currentTuple;
extern int * lastTupleModes;
extern int * C;
extern DppmParams * dppm;
extern int rank, size;

Tuple * makeTupleFromModes(int * startTuple,int numAct);


int FirstBranch(){

//	int debug = 1;
//	while (debug);

	int numAct = dppm->getNumActivities();
	int numTuples = 1;
	int maxActIndex = 0;

	while((maxActIndex < numAct) && (numTuples <= (size-1))){

		numTuples *= dppm->getActivityNumModes(maxActIndex);
		maxActIndex++;

	}

	C = new int[maxActIndex];
	C[maxActIndex - 1] =  1;
	for(int i = maxActIndex - 2; i >= 0; i--){
		C[i] = C[i+1] * dppm->getActivityNumModes(i+1);
	}

	int div = numTuples / (size-1);
	int mod = numTuples % (size-1);

	int firstTupleIndex = (rank-1) < mod ? ((div + 1) * (rank-1) ) : ((div + 1) * mod   +  div * ((rank-1) - mod));
	int lastTupleIndex = (rank) < mod ? ((div + 1) * rank) - 1 : ((div + 1) * mod   +  div * (rank - mod)) - 1;

	int firstTupleModes[numAct];
	lastTupleModes = new int[numAct];

	if(rank == size - 1 ){

		int remainder = firstTupleIndex;

		for(int j = 0 ; j < maxActIndex ; j++){
			firstTupleModes[j] = remainder / C[j];
			remainder = remainder % C[j];
			lastTupleModes[j] = dppm->getActivityNumModes(j) - 1;
		}

		for(int j = maxActIndex; j < numAct; j++){
			firstTupleModes[j] = 0;
			lastTupleModes[j] = dppm->getActivityNumModes(j) - 1;
		}

	}else{

		int remainder1 = firstTupleIndex;
		int remainder2 = lastTupleIndex;

		for(int j = 0 ; j < maxActIndex ; j++){

			firstTupleModes[j] = (remainder1 / C[j]);
			remainder1 = remainder1 % C[j];

			lastTupleModes[j]  = (remainder2 / C[j]);
			remainder2 = remainder2 % C[j];

		}


		for(int j = maxActIndex; j < numAct; j++){
			firstTupleModes[j] = 0;
			lastTupleModes[j] = dppm->getActivityNumModes(j) - 1;
		}

	}



	currentTuple = makeTupleFromModes(firstTupleModes,numAct);

	return 0;
}


Tuple * makeTupleFromModes(int * tupleModes, int numAct){




	Tuple * t = new Tuple();
	int * iter = t->getArray();

	int numPreds = 0;
	int * preds = NULL;
	int maxTimePreds;

	for(int i = 0; i < numAct; i++){

		t->modes(i, tupleModes[i]);

		numPreds = dppm->getActivityNumPreds(i);
		preds = dppm->getActivityPreds(i);

		maxTimePreds = 0;

		for(int j = 0; j < numPreds; j++){

			if(maxTimePreds < t->times(preds[j]) ){
				maxTimePreds = t->times(preds[j]);
			}
		}

		t->times(i, maxTimePreds + dppm->getActivityModesTimes(i)[t->modes(i)] );

		if((i == 0) || (t->partialTimes(i - 1) < t->times(i))){
			t->partialTimes(i, t->times(i));
		}else{
			t->partialTimes(i, t->partialTimes(i - 1));
		}

		if(t->empty()){
			t->cost( dppm->getActivityModesCosts(i)[t->modes(i)] );
		}else{
			t->cost( t->cost() + dppm->getActivityModesCosts(i)[t->modes(i)] );
		}

	}

	return t;
}
